package com.yzy.fly.service.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.yzy.fly.annotation.FlyTableField;
import com.yzy.fly.annotation.OrderSeq;
import com.yzy.fly.annotation.ParentId;
import com.yzy.fly.annotation.RoleChildren;
import com.yzy.fly.config.FlySpringContextUtil;
import com.yzy.fly.entity.role.FlyTableColumn;
import com.yzy.fly.entity.role.ParentIdColumn;
import com.yzy.fly.kernel.model.FlyBasicModel;
import com.yzy.fly.kernel.model.MetadataModel;
import com.yzy.fly.kernel.model.MetadataModelPool;
import com.yzy.fly.kernel.model.ability.sql.DefaultRoleSqlBuilder;
import com.yzy.fly.kernel.model.ability.sql.RoleSqlBuilder;
import com.yzy.fly.kernel.service.FlyBasicService;
import com.yzy.fly.mapper.FlyTableMapper;
import com.yzy.fly.service.cache.MetadataModelCacheKV;
import com.yzy.fly.type.JavaBasicDataType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@Component
public class SqlUtil {

    private static Map<String, MetadataModel> metadataModePool = MetadataModelPool.getInstance().pool();
//    @Autowired
//    private static MetadataModelCache staticMetadataModelCache;

    @Autowired
    private MetadataModelCacheKV metadataModelCache;

//    @PostConstruct
//    public void init() {
//        staticMetadataModelCache = metadataModelCache;
//    }

    /**
     * 建表语句
     *
     * @param cls
     * @return
     */
    public static String createTable(Class<?> cls) throws Exception {
        String className = cls.getName();
        MetadataModel metadataModel = metadataModePool.get(className);
        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        StringBuffer sql = new StringBuffer("");
        if (tableName.startsWith("`") && tableName.endsWith("`")) {

        } else {
            tableName = "`" + tableName + "`";
        }
        sql.append("create table " + tableName + " (");
        //()
        Field[] fields = cls.getDeclaredFields();
        Field fieldTableId = null;
        TableId tableIdAnn = null;
        StringBuffer fieldsSql = new StringBuffer("");
        if (ArrayUtils.isNotEmpty(fields)) {
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];

                if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
                    continue;
                }

                JdbcType ibatisJdbcType = null;
                String jdbcType = "";
                String columnName = "";
                Class<? extends TypeHandler> typeHandler = null;
                boolean annotationTableFieldPresent = field.isAnnotationPresent(TableField.class);
                if (annotationTableFieldPresent) {
                    TableField tableFieldAnn = field.getAnnotation(TableField.class);
                    if (!tableFieldAnn.exist()) {
                        continue;
                    }
                    ibatisJdbcType = tableFieldAnn.jdbcType();
                    jdbcType = ibatisJdbcType.name();
                    columnName = tableFieldAnn.value();
                    typeHandler = tableFieldAnn.typeHandler();
                }
                //check complex object
                Class<?> type = field.getType();

                if (typeHandler != null) {
                    if (FastjsonTypeHandler.class.isAssignableFrom(typeHandler)) {
                        type = JSONObject.class;
                    }
                }
                JavaBasicDataType javaBasicDataType = JavaBasicDataType.javaType(type.getSimpleName(), true);
                if (javaBasicDataType == null) {
                    continue;
                }
                if (ibatisJdbcType == JdbcType.UNDEFINED || StringUtils.isBlank(jdbcType)) {
                    jdbcType = javaBasicDataType.getJdbcType();
                }
                if (StringUtils.isBlank(columnName)) {
                    columnName = field.getName();
                }
                fieldsSql.append("\n").append("    ");

                if (columnName.startsWith("`") && columnName.endsWith("`")) {

                } else {
                    //如果是数据库关键字
//                    if (SQLUtil.keywordCheck(columnName)) {
//                        columnName = "`" + columnName + "`";
//                    }
                    columnName = "`" + columnName + "`";
                }
                fieldsSql.append(columnName).append(" ").append(jdbcType);

                boolean annotationFlyTableFieldPresent = field.isAnnotationPresent(FlyTableField.class);
                int length = 0;
                String defaultValue = "";
                String comment = "";
                boolean notNull = false;
                if (annotationFlyTableFieldPresent) {
                    FlyTableField flyTableFieldAnn = field.getAnnotation(FlyTableField.class);
                    length = flyTableFieldAnn.length();
                    comment = flyTableFieldAnn.comment();
                    notNull = flyTableFieldAnn.notNull();
                    defaultValue = flyTableFieldAnn.defaultValue();
                } else {
                    if (("int").equalsIgnoreCase(jdbcType)) {
                        length = 11;
                        defaultValue = "0";
                    } else if (("varchar").equalsIgnoreCase(jdbcType)) {
                        length = 255;
                        defaultValue = "";
                    } else if (("bigint").equalsIgnoreCase(jdbcType)) {
                        //TODO 20230215
//                        length = 255;
//                        defaultValue = "";
                    } else if (("double").equalsIgnoreCase(jdbcType)) {
                        length = 20;
//                        defaultValue = "";
                    }
                }
                if (StringUtils.equalsIgnoreCase("boolean", type.getSimpleName()) && StringUtils.equalsIgnoreCase("tinyint", jdbcType)) {
                    length = 1;
                }
                if (("timestamp").equalsIgnoreCase(jdbcType)) {
                    notNull = true;
                    defaultValue = "CURRENT_TIMESTAMP";
                }

                if (("double").equalsIgnoreCase(jdbcType)) {
                    fieldsSql.append("(").append(length).append(",").append(6).append(")");
                } else if (("json").equalsIgnoreCase(jdbcType)) {

                } else if (!("timestamp").equalsIgnoreCase(jdbcType)) {
                    fieldsSql.append("(").append(length).append(")");
                }

                if (field.isAnnotationPresent(TableId.class)) {
                    fieldTableId = field;
                    fieldsSql.append(" NOT NULL");
                    tableIdAnn = field.getAnnotation(TableId.class);
                    if (IdType.AUTO == tableIdAnn.type()) {
                        fieldsSql.append(" AUTO_INCREMENT");
                    }
                } else if (notNull) {
                    fieldsSql.append(" NOT NULL DEFAULT ");
                    if (("varchar").equalsIgnoreCase(jdbcType)) {
                        fieldsSql.append("'").append(defaultValue).append("'");
                    } else {
                        fieldsSql.append(defaultValue);
                    }
                } else {
                    fieldsSql.append(" DEFAULT NULL");
                }

                fieldsSql.append(" COMMENT '").append(comment).append("'");
                fieldsSql.append(",");
                boolean annotationTableIdPresent = field.isAnnotationPresent(TableId.class);
                if (annotationTableIdPresent) {
                    fieldTableId = field;
                }
//                    if (i + 1< fields.length ) {
//                        sql.append( ",");
//                    }
            }
        }
        String fieldsSqlStr = fieldsSql.toString();
        if (fieldTableId == null) {
            if (StringUtils.isNotBlank(fieldsSqlStr)) {
                if (fieldsSqlStr.endsWith(",")) {
                    fieldsSqlStr = fieldsSqlStr.substring(0, fieldsSqlStr.length() - 1);
                }
            }
        }
        sql.append(fieldsSqlStr);
        if (fieldTableId != null) {
            sql.append("\n");
            String idColumName = "";
            boolean annotationTableFieldPresent = fieldTableId.isAnnotationPresent(TableField.class);
            if (annotationTableFieldPresent) {
                TableField tableFieldAnn = fieldTableId.getAnnotation(TableField.class);
                idColumName = tableFieldAnn.value();
            }
            if (StringUtils.isBlank(idColumName)) {
                idColumName = fieldTableId.getName();
            }
//            TableId tableIdAnn = fieldTableId.getAnnotation(TableId.class);
            sql.append("   ").append(" PRIMARY KEY").append("(`").append(idColumName).append("`)");
        }

        sql.append("\n");
        sql.append(")");
        sql.append(" ENGINE=InnoDB");

        if (null != tableIdAnn) {
            if (IdType.AUTO == tableIdAnn.type()) {
                sql.append(" AUTO_INCREMENT=").append(1);
            }
        }
        sql.append(" DEFAULT CHARSET=utf8 COMMENT='';");

        String indexSql = createIndexSql(cls);
        if (StringUtils.isNotBlank(indexSql)) {
            sql.append(indexSql);
        }
        return sql.toString();
    }

    /**
     * 建表语句
     *
     * @param cls
     * @return
     */
    public static String createIndexSql(Class<?> cls) throws Exception {
        String className = cls.getName();
//        MetadataModelCache metadataModelCache = SpringContextUtil.getBean("metadataModelCache");
//        MetadataModel metadataModel = metadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);
        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        StringBuffer sqlIndex = new StringBuffer("");

        List<String> indexColumnNames = metadataModel.getIndexColumnNames();
        if (CollectionUtils.isNotEmpty(indexColumnNames)) {
            Map<String, String> indexColumnNamesMap = metadataModel.getIndexColumnNamesMap();
            for (int i = 0; i < indexColumnNames.size(); i++) {
                String indexName = indexColumnNames.get(i);
                String columnName = indexColumnNamesMap.get(indexName);
                sqlIndex.append("create index").append(indexName).append(" on ").append(tableName).append("(").append(columnName).append(")").append("\n");

            }
        }
        //直接创建索引
        // create index index_name on table(column(length))
        return sqlIndex.toString();
    }

    /**
     * 修改表语句 //TODO
     *
     * @param cls
     * @return
     */
    public static String alterTable(Class<?> cls) throws Exception {
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);
        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        FlyTableMapper flyTableMapper = FlySpringContextUtil.getBean("flyTableMapper");
        String tableName = metadataModel.getTableName();
        if (0 == flyTableMapper.checkExsitByTableName(tableName)) {
            return createTable(cls);
        } else {
            StringBuffer alterSql = new StringBuffer("");
            List<String> columnNames = metadataModel.getColumnNames();
            Map<String, FlyTableColumn> columnNamesStructureMap = metadataModel.getColumnNamesStructureMap();
            List<FlyTableColumn> flyTableColumns = flyTableMapper.descByTableName(tableName);
            Map<String, FlyTableColumn> flyTableColumnsMap = Maps.newHashMap();
            for (int i = 0; i < flyTableColumns.size(); i++) {
                FlyTableColumn flyTableColumn = flyTableColumns.get(i);
                flyTableColumnsMap.put(flyTableColumn.getName(), flyTableColumn);
            }

            for (int i = 0; i < columnNames.size(); i++) {
                String sql = "ALTER TABLE " + tableName;
                // ALTER TABLE template_config_column ADD COLUMN matchResultDealType VARCHAR(200) AFTER type;
                String column = columnNames.get(i);
                if (flyTableColumnsMap.containsKey(column)) {
                    continue;
                }

                FlyTableColumn flyTableColumn = columnNamesStructureMap.get(column);
                String type = flyTableColumn.getType();
                Integer length = flyTableColumn.getLength();
                column = " ADD COLUMN " + column + " " + type + "(" + length + ") AFTER type;";
                sql = sql + column;
                alterSql.append(sql).append("\n");
            }
            return alterSql.toString();
        }
    }

    public static String selectSqlSelectListParentId(Class cls, Class parentCls, Object parentId) throws Exception {
//        Class<?> cls = object.getClass();
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
//        if (metadataModel == null) {
//            throw new Exception("未解析数据实体:"+className+",请检查");
//        }
//        MetadataModelCache metadataModelCache = SpringContextUtil.getBean("metadataModelCache");
//        MetadataModel metadataModel = metadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);
        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }

        List<String> outsideParentIdColumnNames = metadataModel.getOutsideParentIdColumnNames();
        StringBuffer sql = new StringBuffer("");
        if (CollectionUtils.isEmpty(outsideParentIdColumnNames)) {
            log.warn("未解析数据实体外键:{},请检查", className);
        } else {
            String tableName = metadataModel.getTableName();
//        String parentIdColumnName = metadataModel.getParentIdColumnName();
//            String parentIdColumnName = outsideParentIdColumnNames.get(0);
            Object parentIdValue = parentId;
            String parentIdColumnName = "";
            StringBuffer sqlTemp = new StringBuffer("");
            StringBuffer sqlTempOtherParentIds = new StringBuffer("");
            Map<String, ParentIdColumn> parentIdColumnNamesAndParentClassMap = metadataModel.getParentIdColumnNamesAndParentClassMap();
            boolean existParentIdColumnName = false;
            boolean isSqlWhereWithOtherParentIds = false;
            for (String parentIdColumnNameKey : parentIdColumnNamesAndParentClassMap.keySet()) {
                ParentIdColumn parentIdColumn = parentIdColumnNamesAndParentClassMap.get(parentIdColumnNameKey);
                Class aClass = parentIdColumn.getParentClass();
                if (Object.class == aClass) {
                    //TODO
//                    aClass = parentIdColumn.getDynamicParentClass();
                    aClass = parentCls;
                }
                if (aClass == parentCls) {
                    existParentIdColumnName = true;
                    isSqlWhereWithOtherParentIds = parentIdColumn.isSqlWhereWithOtherParentIds();
                    sqlTemp.append(" and a.").append(parentIdColumnNameKey).append(" = ").append(parentIdValue);
                } else {
                    sqlTempOtherParentIds.append(" and a.").append(parentIdColumnNameKey).append(" is null ");
                }

                Class<? extends RoleSqlBuilder> roleSqlBuilderClass = parentIdColumn.getRoleSqlBuilder();
                if (DefaultRoleSqlBuilder.class != roleSqlBuilderClass) {
                    RoleSqlBuilder roleSqlBuilder = roleSqlBuilderClass.getConstructor().newInstance();
                    sqlTemp.append(" ").append(roleSqlBuilder.build(cls, parentCls));
                }
            }
            if (existParentIdColumnName) {
                sql.append("select * from " + tableName + " a where 1=1 ");
                sql.append(sqlTemp.toString());
                if (isSqlWhereWithOtherParentIds) {
                    sql.append(sqlTempOtherParentIds.toString());
                }
                //TODO 20230910

            }
        }
        return sql.toString();
    }

    /**
     * 排序语句
     *
     * @param object
     * @return
     */
    public static String orderSqlUpByParentId(Object object) throws Exception {
        Class<?> cls = object.getClass();
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);

        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        String seqColumnName = metadataModel.getSeqColumnName();
        String parentIdColumnName = metadataModel.getParentIdColumnName();

        Object seqValue = getSeqValue(object);
        Object parentIdValue = null;
        List<Field> fields = FieldInvokeUtil.findFieldsByAnnotationPresent(cls, ParentId.class);
        if (CollectionUtils.isNotEmpty(fields)) {
            Field field = fields.get(0);
            Method getterMethod = MethodInvokeUtil.findGetterMethodByField(cls, field);
            parentIdValue = MethodInvokeUtil.invoke(object, getterMethod);
            if (field.getType() == String.class) {
                parentIdValue = "'" + parentIdValue + "'";
            }
        }
        String sql = "update " + tableName + " a set " + seqColumnName + " = " + seqColumnName + " - 1  where " + parentIdColumnName + " = " + parentIdValue + " and " + seqColumnName + " = " + seqValue + " + 1";
        return sql;
    }

    public static String orderSqlDownById(Object object) throws Exception {
        Class<?> cls = object.getClass();
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);

        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        String seqColumnName = metadataModel.getSeqColumnName();
        String idColumName = metadataModel.getIdColumnName();
        Object seqValue = getSeqValue(object);
        Object idValue = null;
        if (cls.isAnnotationPresent(TableName.class)) {
            List<Field> fields = FieldInvokeUtil.findFieldsByAnnotationPresent(cls, TableId.class);
            if (CollectionUtils.isNotEmpty(fields)) {
                Field field = fields.get(0);
                Method getterMethod = MethodInvokeUtil.findGetterMethodByField(cls, field);
                idValue = MethodInvokeUtil.invoke(object, getterMethod);
                if (field.getType() == String.class) {
                    idValue = "'" + idValue + "'";
                }
            }
        }
        String sql = "update " + tableName + " a set " + seqColumnName + " = " + seqColumnName + " + 1  where " + idColumName + " = " + idValue + " and " + seqColumnName + " = " + seqValue + "";
        return sql;
    }


    public static String orderSqlDownByParentId(Object object) throws Exception {
        Class cls = object.getClass();
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);

        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        String seqColumnName = metadataModel.getSeqColumnName();
        String parentIdColumnName = metadataModel.getParentIdColumnName();

        Object seqValue = getSeqValue(object);
        Object parentIdValue = null;
        List<Field> fields = FieldInvokeUtil.findFieldsByAnnotationPresent(cls, ParentId.class);
        if (CollectionUtils.isNotEmpty(fields)) {
            Field field = fields.get(0);
            Method getterMethod = MethodInvokeUtil.findGetterMethodByField(cls, field);
            parentIdValue = MethodInvokeUtil.invoke(object, getterMethod);
            if (field.getType() == String.class) {
                parentIdValue = "'" + parentIdValue + "'";
            }
        }
        String sql = "update " + tableName + " a set " + seqColumnName + " = " + seqColumnName + " + 1  where " + parentIdColumnName + " = " + parentIdValue + " and " + seqColumnName + " = " + seqValue + " - 1";
        return sql;
    }

    public static String orderSqlUpById(Object object) throws Exception {
        Class<?> cls = object.getClass();
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);

        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        String seqColumnName = metadataModel.getSeqColumnName();
        String idColumName = metadataModel.getIdColumnName();
        Object seqValue = getSeqValue(object);
        Object idValue = null;
        List<Field> fields = FieldInvokeUtil.findFieldsByAnnotationPresent(cls, TableId.class);
        if (CollectionUtils.isNotEmpty(fields)) {
            Field field = fields.get(0);
            Method getterMethod = MethodInvokeUtil.findGetterMethodByField(cls, field);
            MethodInvokeUtil.invoke(object, getterMethod);
            if (field.getType() == String.class) {
                idValue = "'" + idValue + "'";
            }
        }
        String sql = "update " + tableName + " a set " + seqColumnName + " = " + seqColumnName + " - 1  where " + idColumName + " = " + idValue + " and " + seqColumnName + " = " + seqValue + "";
        return sql;
    }

    public static String maxSeqNo(Object object) throws Exception {
        Class cls = object.getClass();
        String className = cls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
        MetadataModel metadataModel = metadataModePool.get(className);

        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        String seqColumnName = metadataModel.getSeqColumnName();
        String parentIdColumnName = metadataModel.getParentIdColumnName();
        Object parentIdValue = null;
        List<Field> fields = FieldInvokeUtil.findFieldsByAnnotationPresent(cls, ParentId.class);
        if (CollectionUtils.isNotEmpty(fields)) {
            Field field = fields.get(0);
            Method getterMethod = MethodInvokeUtil.findGetterMethodByField(cls, field);
            parentIdValue = MethodInvokeUtil.invoke(object, getterMethod);
            if (field.getType() == String.class) {
                parentIdValue = "'" + parentIdValue + "'";
            }
        }

        String sql = "select max(" + seqColumnName + ") from " + tableName + " a where 1=1 and " + parentIdColumnName + " = " + parentIdValue;
        return sql;
    }

    private static Object getSeqValue(Object object) {
        Class cls = object.getClass();
        Object seq = null;
        //找seq method比field优先
        List<Method> methods = MethodInvokeUtil.findMethodAnnotationPresent(cls, OrderSeq.class);
        if (CollectionUtils.isNotEmpty(methods)) {
            Method method = methods.get(0);
            seq = MethodInvokeUtil.invoke(object, method);
        } else {
            List<Field> orderSeqFields = FieldInvokeUtil.findFieldsByAnnotationPresent(cls, OrderSeq.class);
            if (CollectionUtils.isNotEmpty(orderSeqFields)) {
                Field orderSeqField = orderSeqFields.get(0);
                Method getterSeqMethod = MethodInvokeUtil.findGetterMethodByField(cls, orderSeqField);
                seq = MethodInvokeUtil.invoke(object, getterSeqMethod);
            }
        }
        return seq;
    }

    public static String select(Class cls) throws Exception {
        return select(cls, false);
    }

    public static String select(Class cls, boolean showColumns) throws Exception {
        String className = cls.getName();
        MetadataModel metadataModel = metadataModePool.get(className);
        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }

        String columnNames = "*";
        if (showColumns) {
            columnNames = metadataModel.getColumnNamesString();
        }

        String sql = "select " + columnNames + " from " + metadataModel.getTableName();
        return sql;
    }

    public static String selectSqlSelectAllByInsideParentIds(Object object) throws Exception {
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(object));
        return selectSqlSelectAllByInsideParentIds(jsonObject);
    }

    public static String selectSqlSelectAllByInsideParentIds(Class cls, JSONObject jsonObject) throws Exception {
        String className = cls.getName();
        MetadataModel metadataModel = metadataModePool.get(className);

        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        StringBuffer sql = new StringBuffer();
        sql.append("select * from ").append(tableName).append(" where 1=1");
        List<String> insideParentIdColumnNames = metadataModel.getInsideParentIdColumnNames();
        Map<String, String> insideParentIdColumnNamesMap = metadataModel.getInsideParentIdColumnNamesMap();
        for (int i = 0; i < insideParentIdColumnNames.size(); i++) {
            String insideParentIdColumnName = insideParentIdColumnNames.get(i);
            String fieldName = insideParentIdColumnNamesMap.get(insideParentIdColumnName);
            Object parentIdValue = jsonObject.get(fieldName);
            sql.append(" and ").append(insideParentIdColumnName).append(" = ").append(parentIdValue);
        }
        return sql.toString();
    }

    public static String deleteByParentId(Class cls, int parentId) throws Exception {
        String className = cls.getName();
        MetadataModel metadataModel = metadataModePool.get(className);
        if (metadataModel == null) {
            throw new Exception("未解析数据实体:" + className + ",请检查");
        }
        String tableName = metadataModel.getTableName();
        StringBuffer sql = new StringBuffer("");
        sql.append("delete a from " + tableName + " a where 1=1 ");
        String parentIdColumnName = metadataModel.getOutsideParentIdColumnNames().get(0);
        sql.append("and a.").append(parentIdColumnName).append(" = ").append(parentId);
        String deleteSql = sql.toString();
        return deleteSql;
    }

//    public static String relatedQuery(int id,Class selfCls,Class<? extends FlyBasicEntity>... relatedClasses) throws Exception{
//
//        String className = selfCls.getName();
//        MetadataModel metadataModel = staticMetadataModelCache.get(className);
//        if (metadataModel == null) {
//            throw new Exception("未解析数据实体:"+className+",请检查");
//        }
//        String tableName = metadataModel.getTableName();
//
//        List<String> columnNames = metadataModel.getColumnNames();
//        String alias = "a";
////        sql.append("select * from " + tableName + " a where 1=1 ");
////        relatedTableName
//        Map<Class<? extends FlyBasicEntity>,FlyTableColumn> relatedModelMaps = metadataModel.getRelatedModelMap();
//        if (MapUtils.isNotEmpty(relatedModelMaps)) {
//            Set<Class<? extends FlyBasicEntity>> relatedKeySet = relatedModelMaps.keySet();
//            for (Class<? extends FlyBasicEntity> relatedClass: relatedKeySet){
//                String relatedClassName = relatedClass.getName();
//                //related
//                MetadataModel relatedMetadataModel = staticMetadataModelCache.get(relatedClassName);
//                String relatedTableName = relatedMetadataModel.getTableName();
//                List<String> relatedColumnNames = relatedMetadataModel.getColumnNames();
//                String relatedAlias = "b";
//                String type = "";
//                if(RelatedType.MANYTOMANY.equals(type)){
//
//                } else if(RelatedType.ONETOMANY.equals(type)){
//                    StringBuffer sql = new StringBuffer("");
//                    sql.append("select a.* from").append(tableName).append(" ").append(alias).append(",").append(relatedTableName).append(" ").append(relatedAlias)
//                            .append(metadataModel.getIdColumnName()).append("=").append(alias).append(relatedMetadataModel.getParentIdColumnName());
//                } else if(RelatedType.MANYTOONE.equals(type)){
//
//                } else if(RelatedType.ONETOONE.equals(type)){
//
//                }
//            }
////            relatedKeySet.
////            relatedModelMaps.containsKey();
//        }
////        for (int i = 0; i < relatedClasses.length; i++) {
////            Class<? extends FlyBasicEntity> relatedClass = relatedClasses[i];
////            String relatedClassName = relatedClass.getName();
////            MetadataModel relatedMetadataModel = staticMetadataModelCache.get(relatedClassName);
////            String relatedTableName = relatedMetadataModel.getTableName();
////
////            relatedMetadataModel.getOutsideParentIdColumnNamesMap();
//////            select * from relatedTableName;
////        }
//
////        StringBuffer sql = new StringBuffer("");
////        sql.append("delete a from " + tableName + " a where 1=1 ");
////        String parentIdColumnName = metadataModel.getOutsideParentIdColumnNames().get(0);
////        sql.append("and a.").append(parentIdColumnName).append(" = ").append(parentId);
////        String deleteSql = sql.toString();
//        return "";
//    }

    public static String offlineCreateTableSql(String packageName) throws Exception {
        Reflections reflections = new Reflections(packageName);
        Set<Class<? extends FlyBasicModel>> classes = reflections.getSubTypesOf(FlyBasicModel.class);
//        for (Class<?> clazz : classes) {
//            System.out.println(clazz.getName());
//        }
        return offlineCreateTableSql(classes);
    }

    /**
     * 建表语句(离线)
     *
     * @param entityClasses
     * @return
     */
    public static String offlineCreateTableSql(Class<? extends FlyBasicModel>... entityClasses) throws Exception {
//        Map<String, MetadataModel> metadataModePool = MetadataModelPool.getInstance().pool();
        Set<Class<? extends FlyBasicModel>> entityClassSet = Sets.newLinkedHashSet();
        for (int i = 0; i < entityClasses.length; i++) {
            Class<? extends FlyBasicModel> entityClass = entityClasses[i];
            entityClassSet.add(entityClass);
            Field[] declaredFields = entityClass.getDeclaredFields();
            for (int j = 0; j < declaredFields.length; j++) {
                Field field = declaredFields[j];
                boolean isAnnoPresent = field.isAnnotationPresent(RoleChildren.class);
                if (isAnnoPresent) {
                    RoleChildren roleChildrenAnno = field.getAnnotation(RoleChildren.class);
//                    Class<?> fieldType = field.getType();
//                    Type fieldGenericType = field.getGenericType();
//                    if (!fieldType.isAssignableFrom(FlyBasicModel.class)) {
//                        continue;
//                    }
                    Class<?> requiredModelType = FlyBasicService.findRequiredModelType(field, roleChildrenAnno);
                    if (requiredModelType != null) {
                        entityClassSet.add((Class<? extends FlyBasicModel>) requiredModelType);
                    }
                }
            }
        }
        return offlineCreateTableSql(entityClassSet);
    }

    public static String offlineCreateTableSql(Set<Class<? extends FlyBasicModel>> entityClasses) throws Exception {
        StringBuffer stringBuffer = new StringBuffer("");
        for (Class<? extends FlyBasicModel> entityClass : entityClasses) {
            String className = entityClass.getName();
            MetadataModel metadataModel = metadataModePool.get(className);
            if (metadataModel == null) {
                metadataModel = new MetadataModel();
                metadataModePool.put(className, metadataModel);
                new MetadataModelParse(metadataModel).exec(entityClass);
            }
//            ModelConfig modelConfig = ModelConfigPool.getInstance().get(className);
            String sql = "";
            try {
                sql = createTable(entityClass);
            } catch (Exception var3) {
                var3.printStackTrace();
            }
            stringBuffer.append("-- ").append(className + ":").append("\n");
            stringBuffer.append(sql).append("\n");
        }
        return stringBuffer.toString();
    }
}
